/*
 *接口编写处...
*如果接口需要做Action的权限验证，请在Action上使用属性
*如: [ApiActionPermission("StagingArea",Enums.ActionPermissionOptions.Search)]
 */
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using Mercury.Entity.DomainModels;
using Mercury.Business.IServices;
using Mercury.Core.Utilities;
using Mercury.Business.IRepositories;
using System.Linq;
using Mercury.Core.Extensions;
using Microsoft.EntityFrameworkCore;

namespace Mercury.Business.Controllers
{
    public partial class StagingAreaController
    {
        private readonly IStagingAreaService _service;//访问业务代码
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IStagingAreaRepository _repository;

        [ActivatorUtilitiesConstructor]
        public StagingAreaController(
            IStagingAreaService service,
            IStagingAreaRepository stagingAreaRepository,
            IHttpContextAccessor httpContextAccessor
        )
        : base(service)
        {
            _service = service;
            _httpContextAccessor = httpContextAccessor;
            _repository = stagingAreaRepository;
        }

        [Route("GetStagingAreas"), HttpGet]
        public async Task<WebResponseContent> GetStagingAreas()
        {
            var areas = await _repository.FindAsync(c => c.Enable == 1);
            var data = areas.Select(c => new { c.Id, c.RegionName, c.RegionNo, ParentId = "-" }).OrderBy(c => c.RegionNo);
            return new WebResponseContent() { Status = true, Data = data };
        }

        [Route("GetLocationData/{id}"), HttpGet]
        public async Task<WebResponseContent> GetLocationData(string id)
        {
            var joinQueryable = from p in _repository.DbContext.Set<StagingLocation>().Where(c => c.StagingAreaId == id && c.DeletionFlag != 1)
                           join d in _repository.DbContext.Set<MaterialBox>()
                           on p.MaterialBoxNo equals d.BoxNo into DD
                           from dc in DD.DefaultIfEmpty()
                           select new
                           {
                               p.Enable,
                               p.IsOccupy,
                               p.SLName,
                               p.TheColumn,
                               p.TheRow,
                               p.MaterialBoxNo   ,
                               dc.MaterialName,
                               dc.MaterialId,
                               dc.BatchNumber,
                               dc.OrderNumber  ,
                               p.Sort  ,
                               dc.MaterialWeight
                           };

            var data = joinQueryable.ToList();
                //_repository.DbContext.Set<StagingLocation>().Where(c => c.StagingAreaId == id && c.DeletionFlag != 1).ToList();

            var rows = data.OrderBy(c => c.Sort).GroupBy(c => c.TheRow).Select(c => new
            {
                c.Key,
                Sort = c.Min(x => x.Sort),
                Data = c.ToList()
            });

            var result = new List<Dictionary<string, object>>();
            var rowsList = rows.OrderBy(c => c.Sort).ToList();
            for (int i = 0; i < rowsList.Count(); i++)
            {
                var dic = new Dictionary<string, object>();
                dic.Add("Key", rowsList[i].Key);

                StagingLocation last = null;
                var tempList = rowsList[i].Data.OrderBy(c => c.TheColumn).ToList();
                var tmpCol = tempList.Select(c =>
                {
                    var tempLocation = new StagingLocation() 
                    {
                        TheColumn = c.TheColumn,
                        TheRow = c.TheRow
                    };
                    var offset = 0;
                    if (last == null)
                    {
                        if (tempLocation.TheColumn > 1)
                        {
                            offset = tempLocation.TheColumn.Value - 1;
                        }
                    }
                    else if (last.TheColumn == tempLocation.TheColumn)
                    {
                        tempLocation.TheColumn += 1;
                    }
                    else if (last.TheColumn + 1 != tempLocation.TheColumn && tempLocation.TheColumn.HasValue)
                    {
                        offset = tempLocation.TheColumn.Value - last.TheColumn.Value - 1;
                    }
                    last = tempLocation;
                    return new
                    {
                        c.Enable,
                        c.IsOccupy,
                        c.SLName,
                        c.TheColumn,
                        c.TheRow,
                        Offset = offset,
                        c.MaterialBoxNo  ,
                        c.MaterialId,
                        c.MaterialName,
                        c.OrderNumber,
                        c.BatchNumber  ,
                        c.MaterialWeight
                    };
                });
                dic.Add("Cols", tmpCol);
                result.Add(dic);
            }
            var maxCol = rows.Max(c => c.Data.Max(c => c.TheColumn));
            return new WebResponseContent() { Status = true, Data = new { Span = 24 / maxCol, Result = result } };
        }


        [Route("GetBoxStock/{boxNo}"), HttpGet]
        public async Task<WebResponseContent> GetBoxStock(string boxNo)
        {
            var resposne = new WebResponseContent();
            if (string.IsNullOrEmpty(boxNo))
            {
                return resposne.Error("该位置未绑定料箱号！");
            }
            var data = await _repository.DbContext.Set<MaterialBox>().FirstAsync(c => c.BoxNo == boxNo);
            return resposne.OK(data: data);
        }

    }
}
